package com.hss01248.dialog.material;


import com.hss01248.dialog.ResourceTable;
import com.hss01248.dialog.comp.AlertDialog;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.service.*;
import ohos.app.Context;
import ohos.agp.components.Text.TextSizeType;

import java.util.Optional;

/**
 * Created by drakeet on 9/28/14.
 */
public class MaterialDialog {

    private static int BUTTON_BOTTOM = 9;
    private static int BUTTON_TOP = 9;

    private boolean mCancel;
    private Context mContext;
    private AlertDialog mAlertDialog;
    private Builder mBuilder;
    private Component mView;
    private int mTitleResId;
    private CharSequence mTitle;
    private int mMessageResId;
    private CharSequence mMessage;
    private Button mPositiveButton;
    private Button mNegativeButton;
    private boolean mHasShow = false;
    private int mBackgroundResId = -1;
    private Component mMessageContentView;
    private int mMessageContentViewResId;
    private CommonDialog.DestroyedListener mOnDismissListener;
    private int pId = -1, nId = -1;
    private String pText, nText;
    Component.ClickedListener pListener, nListener;


    public MaterialDialog(Context context) {
        this.mContext = context;
    }


    public void show() {
        if (!mHasShow) {
            mBuilder = new Builder();
        } else {
            mAlertDialog.show();
        }
        mHasShow = true;
    }


    public MaterialDialog setView(Component view) {
        mView = view;
        if (mBuilder != null) {
            mBuilder.setView(view);
        }
        return this;
    }


    public MaterialDialog setContentView(Component view) {
        mMessageContentView = view;
        mMessageContentViewResId = 0;
        if (mBuilder != null) {
            mBuilder.setContentView(mMessageContentView);
        }
        return this;
    }


    /**
     * Set a custom view resource to be the contents of the dialog.
     *
     * @param layoutResId resource ID to be inflated
     */
    public MaterialDialog setContentView(int layoutResId) {
        mMessageContentViewResId = layoutResId;
        mMessageContentView = null;
        if (mBuilder != null) {
            mBuilder.setContentView(layoutResId);
        }
        return this;
    }

    public MaterialDialog setBackgroundResource(int resId) {
        mBackgroundResId = resId;
        if (mBuilder != null) {
            mBuilder.setBackgroundResource(mBackgroundResId);
        }
        return this;
    }


    public void dismiss() {
        mAlertDialog.destroy();
    }


    private int dip2px(float dpValue) {
        Optional<Display> display = DisplayManager.getInstance().getDefaultDisplay(mContext);
        DisplayAttributes attrs = display.get().getAttributes();
        final float scale = attrs.scalDensity;
        return (int) (dpValue * scale + 0.5f);
    }

    public MaterialDialog setTitle(int resId) {
        mTitleResId = resId;
        if (mBuilder != null) {
            mBuilder.setTitle(resId);
        }
        return this;
    }


    public MaterialDialog setTitle(CharSequence title) {
        mTitle = title;
        if (mBuilder != null) {
            mBuilder.setTitle(title);
        }
        return this;
    }


    public MaterialDialog setMessage(int resId) {
        mMessageResId = resId;
        if (mBuilder != null) {
            mBuilder.setMessage(resId);
        }
        return this;
    }


    public MaterialDialog setMessage(CharSequence message) {
        mMessage = message;
        if (mBuilder != null) {
            mBuilder.setMessage(message);
        }
        return this;
    }


    public MaterialDialog setPositiveButton(int resId, final Component.ClickedListener listener) {
        this.pId = resId;
        this.pListener = listener;
        return this;
    }


    public Button getPositiveButton() {
        return mPositiveButton;
    }


    public Button getNegativeButton() {
        return mNegativeButton;
    }


    public MaterialDialog setPositiveButton(String text, final Component.ClickedListener listener) {
        this.pText = text;
        this.pListener = listener;
        return this;
    }


    public MaterialDialog setNegativeButton(int resId, final Component.ClickedListener listener) {
        this.nId = resId;
        this.nListener = listener;
        return this;
    }


    public MaterialDialog setNegativeButton(String text, final Component.ClickedListener listener) {
        this.nText = text;
        this.nListener = listener;
        return this;
    }


    /**
     * Sets whether this dialog is canceled when touched outside the window's
     * bounds OR pressed the back key. If setting to true, the dialog is
     * set to be cancelable if not
     * already set.
     *
     * @param cancel Whether the dialog should be canceled when touched outside
     * the window OR pressed the back key.
     */
    public MaterialDialog setCanceledOnTouchOutside(boolean cancel) {
        this.mCancel = cancel;
        if (mBuilder != null) {
            mBuilder.setCanceledOnTouchOutside(mCancel);
        }
        return this;
    }
    public MaterialDialog setDestroyedListener(CommonDialog.DestroyedListener destroyedListener) {
        this.mOnDismissListener = destroyedListener;
        return  this;
    }

    private boolean isNullOrEmpty(String nText) {
        return nText == null || nText.isEmpty();
    }


    private void setListViewHeightBasedOnChildren(ListContainer listView) {
        BaseItemProvider listAdapter = listView.getItemProvider();
        if (listAdapter == null) {
            // pre-condition
            return;
        }

        int totalHeight = 0;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            Component listItem = listAdapter.getComponent(i, null, listView);
            listItem.estimateSize(0, 0);
            totalHeight += listItem.getEstimatedHeight();
        }

        ComponentContainer.LayoutConfig params = listView.getLayoutConfig();
        params.height = totalHeight + (1 * (listAdapter.getCount() - 1));
        listView.setLayoutConfig(params);
    }
    private final class Builder {

        private Text mTitleView;
        private ComponentContainer mMessageContentRoot;
        private Text mMessageView;
        private Window mAlertDialogWindow;
        private DirectionalLayout mButtonLayout;


        private Builder() {
            mAlertDialog = new AlertDialog.Builder(mContext).create();
            mAlertDialog.show();

            mAlertDialog.getWindow()
                        .clearFlags(WindowManager.LayoutConfig.MARK_FOCUSABLE_IMPOSSIBLE |
                                WindowManager.LayoutConfig.MARK_ALT_FOCUSABLE_IM);
            mAlertDialog.getWindow()
                        .setInputPanelDisplayType(WindowManager.LayoutConfig.INPUT_MASK_STATE);

            mAlertDialogWindow = mAlertDialog.getWindow();
            mAlertDialogWindow.setBackgroundColor(RgbColor.fromRgbaInt(ohos.agp.utils.Color.TRANSPARENT.getValue()));
            LayoutScatter scatter = LayoutScatter.getInstance(mContext);
            Component contentView = scatter.parse(ResourceTable.Layout_alertdialog, null, false); //R.layout.layout_material_dialog

            contentView.setFocusable(Component.FOCUS_ENABLE);
            contentView.setTouchFocusable(true);

            mButtonLayout = (DirectionalLayout) contentView.findComponentById(ResourceTable.Id_alertbuttonlist);
            mPositiveButton = (Button) mButtonLayout.findComponentById(ResourceTable.Id_alertokbtn);
            mNegativeButton = (Button) mButtonLayout.findComponentById(ResourceTable.Id_alertcancelbtn);
            mMessageContentRoot = (ComponentContainer) contentView.findComponentById(
                   ResourceTable.Id_alertlist);
            if (mView != null) {
                DirectionalLayout linearLayout = (DirectionalLayout) contentView.findComponentById(
                        ResourceTable.Id_alert_main);
                linearLayout.removeAllComponents();
                linearLayout.addComponent(mView);
            }
            if (mTitleResId != 0) {
                setTitle(mTitleResId);
            }
            if (mTitle != null) {
                setTitle(mTitle);
            }
            if (mTitle == null && mTitleResId == 0) {
                mTitleView.setVisibility(Component.HIDE);
            }
            if (mMessageResId != 0) {
                setMessage(mMessageResId);
            }
            if (mMessage != null) {
                setMessage(mMessage);
            }
            if (pId != -1) {
                mPositiveButton.setVisibility(Component.VISIBLE);
                mPositiveButton.setText(pId);
                mPositiveButton.setClickedListener(pListener);
            }
            if (nId != -1) {
                mNegativeButton.setVisibility(Component.VISIBLE);
                mNegativeButton.setText(nId);
                mNegativeButton.setClickedListener(nListener);
            }
            if (!isNullOrEmpty(pText)) {
                mPositiveButton.setVisibility(Component.VISIBLE);
                mPositiveButton.setText(pText);
                mPositiveButton.setClickedListener(pListener);
            }

            if (!isNullOrEmpty(nText)) {
                mNegativeButton.setVisibility(Component.VISIBLE);
                mNegativeButton.setText(nText);
                mNegativeButton.setClickedListener(nListener);
            }
            if (isNullOrEmpty(pText) && pId == -1) {
                mPositiveButton.setVisibility(Component.HIDE);
            }
            if (isNullOrEmpty(nText) && nId == -1) {
                mNegativeButton.setVisibility(Component.HIDE);
            }
            if (mBackgroundResId != -1) {
                DirectionalLayout linearLayout = (DirectionalLayout) contentView.findComponentById(
                        ResourceTable.Id_alert_main);
                linearLayout.setBackground(new ShapeElement(mContext, mBackgroundResId));
            }

            if (mMessageContentView != null) {
                this.setContentView(mMessageContentView);
            } else if (mMessageContentViewResId != 0) {
                this.setContentView(mMessageContentViewResId);
            }
            mAlertDialog.setAutoClosable(mCancel);
            mAlertDialog.siteRemovable(mCancel);
            if (mOnDismissListener != null) {
                mAlertDialog.setDestroyedListener(mOnDismissListener);
            }
        }


        public void setTitle(int resId) {
            mTitleView.setText(resId);
        }


        public void setTitle(CharSequence title) {
            mTitleView.setText(title.toString());
        }


        public void setMessage(int resId) {
            if (mMessageView != null) {
                mMessageView.setText(resId);
            }
        }


        public void setMessage(CharSequence message) {
            if (mMessageView != null) {
                mMessageView.setText(message.toString());
            }
        }


        /**
         * set positive button
         *
         * @param text the name of button
         */
        public void setPositiveButton(String text, final Component.ClickedListener listener) {
            Button button = new Button(mContext);
            DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(
                    DirectionalLayout.LayoutConfig.MATCH_CONTENT, DirectionalLayout.LayoutConfig.MATCH_CONTENT);
            params.alignment = LayoutAlignment.CENTER;
            button.setLayoutConfig(params);
            button.setBackground(new ShapeElement(mContext, 0));//R.drawable.material_card);
            button.setTextColor(new ohos.agp.utils.Color(ohos.agp.utils.Color.argb(255, 35, 159, 242)));
            button.setText(text);
            button.setTextSize(14, TextSizeType.FP);
            button.setPadding(dip2px(12), 0, dip2px(32), dip2px(BUTTON_BOTTOM));
            button.setClickedListener(listener);
            mButtonLayout.addComponent(button);
        }


        /**
         * set negative button
         *
         * @param text the name of button
         */
        public void setNegativeButton(String text, final  Component.ClickedListener listener) {
            Button button = new Button(mContext);
            DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(
                    DirectionalLayout.LayoutConfig.MATCH_CONTENT, DirectionalLayout.LayoutConfig.MATCH_CONTENT);
            params.alignment = LayoutAlignment.CENTER;
            button.setLayoutConfig(params);
            button.setBackground(new ShapeElement(mContext, 0));//R.drawable.material_card);
            button.setText(text);
            button.setTextColor(new ohos.agp.utils.Color(ohos.agp.utils.Color.argb(222, 0, 0, 0)));
            button.setTextSize(14, TextSizeType.FP);
            button.setPadding(0, 0, 0, dip2px(8));
            button.setClickedListener(listener);
            if (mButtonLayout.getChildCount() > 0) {
                params.setMargins(20, 0, 10, dip2px(BUTTON_BOTTOM));
                button.setLayoutConfig(params);
                mButtonLayout.addComponent(button, 1);
            } else {
                button.setLayoutConfig(params);
                mButtonLayout.addComponent(button);
            }
        }


        public void setView(Component view) {
            DirectionalLayout l =
                    (DirectionalLayout) mAlertDialog.getContentCustomComponent().findComponentById(ResourceTable.Id_alert_main);//findViewById(R.id.contentView);
            l.removeAllComponents();
            ComponentContainer.LayoutConfig layoutParams = new ComponentContainer.LayoutConfig(
                    ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT);
            view.setLayoutConfig(layoutParams);

            view.setFocusChangedListener(new ComponentContainer.FocusChangedListener() {
                @Override
                public void onFocusChange(Component v, boolean hasFocus) {
                }
            });

            l.addComponent(view);


            if (view instanceof ComponentContainer) {

                ComponentContainer viewGroup = (ComponentContainer) view;

                for (int i = 0; i < viewGroup.getChildCount(); i++) {
                    if (viewGroup.getComponentAt(i) instanceof Text) {
                        Text editText = (Text) viewGroup.getComponentAt(i);
                        editText.setFocusable(Component.FOCUS_ENABLE);
                        editText.requestFocus();
                        editText.setTouchFocusable(true);
                    }
                }
            }
        }


        public void setContentView(Component contentView) {
            ComponentContainer.LayoutConfig layoutParams = new ComponentContainer.LayoutConfig(
                    ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
            contentView.setLayoutConfig(layoutParams);
            if (contentView instanceof ListContainer) {
                setListViewHeightBasedOnChildren((ListContainer) contentView);
            }

            DirectionalLayout linearLayout = (DirectionalLayout) mAlertDialog.getContentCustomComponent().findComponentById(
                    ResourceTable.Id_alert_main);
            if (linearLayout != null) {
                linearLayout.removeAllComponents();
                linearLayout.addComponent(contentView);
            }
        }


        /**
         * Set a custom view resource to be the contents of the dialog. The
         * resource will be inflated into a ScrollView.
         *
         * @param layoutResId resource ID to be inflated
         */
        public void setContentView(int layoutResId) {
            mMessageContentRoot.removeAllComponents();
            LayoutScatter scatter = LayoutScatter.getInstance(mContext);
            scatter.parse(ResourceTable.Id_alert_main, mMessageContentRoot, true);
        }

        public void setBackgroundResource(int resId) {
            DirectionalLayout linearLayout = (DirectionalLayout) mAlertDialog.getContentCustomComponent().findComponentById(
                    ResourceTable.Id_alert_main);
            linearLayout.setBackground(new ShapeElement(mContext, resId));
        }

        public void setCanceledOnTouchOutside(boolean canceledOnTouchOutside) {
            mAlertDialog.setAutoClosable(canceledOnTouchOutside);
            mAlertDialog.siteRemovable(canceledOnTouchOutside);
        }
    }


}

